﻿using System;
using System.Collections.Generic;
using System.Windows.Input;

using iStudio.Structure.Command;
using iStudio.Structure.Control.Module;
using iStudio.Structure.Message;

namespace iStudio.Structure.Engine
{
    public abstract class Module : MessageClient
    {
        #region Fields

        private ModuleWindow _window;

        #endregion

        #region Properties
        public List<ModuleCommand> Commands
        {
            get;
            private set;
        }

        public string ModuleName
        {
            get
            {
                return GetType ().Name;
            }
        }

        #endregion

        #region Constructor

        protected Module()
        {
            Subscribe (MessageServer.Instance);

            Commands = new List<ModuleCommand> ();
        }

        #endregion

        #region Module API
        /// <summary>
        /// Setups module window as a single module window
        /// </summary>
        /// <param name="window"></param>
        protected void SetupModuleWindow (ModuleWindow window)
        {
            _window = window;
            _window.HideOnClose = true;
        }

        /// <summary>
        /// Returns if the module has a single module window setuped
        /// </summary>
        /// <returns>true if window is set</returns>
        protected bool HasModuleWindow ()
        {
            return (_window != null);
        }

        /// <summary>
        /// Opens module window if it is setuped
        /// </summary>
        protected void OpenModuleWindow ()
        {
            if (_window != null)
            {
                OpenDockableWindow (_window);
            }
        }

        /// <summary>
        /// Logs text on main window
        /// </summary>
        /// <param name="log">string to log</param>
        public void ConsoleLog (string log)
        {
            object[] msg = new object[2];
            msg[0] = "ConsoleLog";
            msg[1] = log;

            MessageServer.Instance.Push (new Message.Message
                                             {
                                                 Parameters = msg
                                             });
        }

        /// <summary>
        /// Adds new module command
        /// </summary>
        /// <param name="name">command name</param>
        /// <param name="text">menu text</param>
        protected void AddCommand (string name, string text)
        {
            AddCommand (name, text, ModuleCommandTypes.MainMenu);
        }

        /// <summary>
        /// Adds new module command
        /// </summary>
        /// <param name="name">command name</param>
        /// <param name="text">menu text</param>
        /// <param name="type">command type</param>
        protected void AddCommand (string name, string text, ModuleCommandType type)
        {
            ModuleCommand command = new ModuleCommand (name, GetType ())
                                        {
                                            CommandType = type,
                                            Text = text
                                        };

            Commands.Add(command);
        }

        /// <summary>
        /// Adds new module command
        /// </summary>
        /// <param name="name">command name</param>
        /// <param name="text">menu text</param>
        /// <param name="type">command type</param>
        /// <param name="parameter">command parameters</param>
        protected void AddCommand (string name, string text, ModuleCommandType type, object parameter)
        {
            ModuleCommand command = new ModuleCommand (name, GetType())
                                        {
                                            Text = text,
                                            CommandType = type,
                                            Parameter = parameter
                                        };

            Commands.Add(command);
        }

        /// <summary>
        /// Overridable method to handle commands
        /// </summary>
        /// <param name="command">Command to handle</param>
        protected virtual void OnExecutedCommand(ModuleCommand command)
        {

        }

        /// <summary>
        /// Opens dockable window on main UI
        /// </summary>
        /// <param name="window">Dockable window</param>
        protected void OpenDockableWindow(AvalonDock.DockableContent window)
        {
            MessageDialog msg = new MessageDialog
            {
                Dialog = window
            };

            MessageServer.Instance.Push(msg);
        }

        /// <summary>
        /// Message error handler
        /// </summary>
        /// <param name="error"></param>
        public override void OnError(Exception error)
        {
            ConsoleLog("Module error: " + error.Message);
        }

        /// <summary>
        /// Message handler, should be implemented if you need any kind of communication
        /// </summary>
        /// <param name="message">Received message</param>
        public override void OnNext (Message.Message message)
        {
            
        }

        /// <summary>
        /// Send message to other modules and main window
        /// </summary>
        /// <param name="message">Message to send</param>
        protected void PushMessage (Message.Message message)
        {
            MessageServer.Instance.Push (message);
        }

        #endregion

        #region Private Methods
        /// <summary>
        /// Event handler for all executed commands
        /// </summary>
        /// <param name="target"></param>
        /// <param name="e"></param>
        public void ExecutedCommand (object target, ExecutedRoutedEventArgs e)
        {
            ConsoleLog ("Executed command: " + ((ModuleCommand)e.Command).Name + " " + ((ModuleCommand)e.Command).Parameter);
            OnExecutedCommand ((ModuleCommand) e.Command);
        }

        #endregion
    }
}
